﻿/*
ParallelPlatform Project - A web platform to distribute and share knowledge
Online Editor - An online tool to create and play animations
Copyright (C) 2011 Daniel Guerrero Martínez & Sergio Rodríguez Lumley

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package Classes{
	
	import flash.display.MovieClip;
	import flash.geom.Point;
	
	public class PaintLine extends MovieClip{
		
		private var points:Vector.<Point>;
		private var color:uint;
		
		public function PaintLine(){
			points = new Vector.<Point>();
		}
		
		public function addPoint(px:Number, py:Number):void{
			points.push(new Point(px, py));
			this.repaint();
		}
		
		/**
		  Centers all the points of this line, assuming
		  that the old center was (0,0) and now it is the
		  one specified by center.
		  @param center Point that marks the new center
		*/
		public function centerIn(center:Point):void{
			for each(var point:Point in points){
				point.x = point.x - center.x;
				point.y = point.y - center.y;
			}
		}
		
		public function getColor():uint{
			return color;
		}
		
		/**
		  Gets the maximum value of X and Y of all the points, note
		  the point it returns it is not necessarily an existing one,
		  just one created by the maximum values of X and Y
		  @return Point with the maximum values of X and Y
		*/
		public function getMaxPoint():Point{
			var numx:Number = Number.MIN_VALUE;
			var numy:Number = Number.MIN_VALUE;
			for each(var point:Point in points){
				if(point.x > numx) numx = point.x;
				if(point.y > numy) numy = point.y;
			}
			return new Point(numx, numy);
		}
		
		/**
		  Gets the minimum value of X and Y of all the points, note
		  the point it returns it is not necessarily an existing one,
		  just one created by the minimum values of X and Y
		  @return Point with the minimum values of X and Y
		*/
		public function getMinPoint():Point{
			var numx:Number = Number.MAX_VALUE;
			var numy:Number = Number.MAX_VALUE;
			for each(var point:Point in points){
				if(point.x < numx) numx = point.x;
				if(point.y < numy) numy = point.y;
			}
			return new Point(numx, numy);
		}
		
		/**
		  Returns all the points in array form
		  @return Array with all the points of the line
		*/
		public function getPointsArray():Array{
			var array:Array = new Array(points.length);
			for(var i=0; i<points.length; ++i){
				array[i] = points[i];
			}
			return array;
		}
		
		/**
		  Optimize currLine erasing all irrelevant points,
		  this can be done getting the orientation vector
		  between two points and removing those that have
		  less than 5º of difference
		*/
		public function optimize():void{
			var ref:		uint;
			var threshold:	Number = 10;
			var angle:		Number;
			var refangle:	Number;
			var i:			int; // Necessarily not unsigned, in order to let splice work correctly
			
			//trace("Initial points: "+String(points.length));
			for(i = points.length-3; i > 1; i -=3){ // We delete all impair points
				points.splice(i, 2);
			}
			
			ref = points.length-1;
			for(i = points.length-2; i > 0; --i){ 
				if(ref - i <= 1){
					refangle = getAngle(points[ref], points[i]);
				}else{
					angle = getAngle(points[ref-1], points[i]);
					if(Math.abs(refangle-angle) < threshold ||
						Math.abs(refangle-angle) > 360-threshold){
						points.splice(i+1, 1);
						--ref;
					}else{
						ref = i+1;
					}
					refangle = getAngle(points[ref], points[i]);
				}
			}
			//trace("Ending points: "+String(points.length));
			this.repaint();
		}
		
		public function repaint():void{
			graphics.clear();
			graphics.lineStyle(5, color);
			graphics.moveTo(points[0].x, points[0].y);
			for (var i:uint = 1; i<points.length; ++i){
				graphics.lineTo(points[i].x, points[i].y);
			}
		}
		
		public function setColor(c:uint):void{
			color = c;
		}
		
		// ------------ PRIVATE FUNCTIONS ------------- //
		
		/**
		  Gets the angle expressed between [0, 360) between two given points,
		  respect horizontal line
		  @param p1 Point origin of the vector
		  @param p1 Point dest of the vector
		  @return Number angle
		*/
		private function getAngle(p1:Point, p2:Point):Number{
			var rot:Number = Math.atan2(p2.y - p1.y, p2.x - p1.x)*180/Math.PI;
			if(rot < 0) rot = 360 + rot;
			else if(rot >= 360){
				while(rot >= 360){
					rot = rot-360;
				}
			}
			return rot;
		}
		
		/**
		  Removes the point specified by the index from 'points'
		  @param p uint with the index of the point
		*
		private function removePoint(pos:uint):void{
			var p:Point;
			while(pos < points.length-1){
				p = points[pos];
				points[pos] = points[pos+1];
				points[pos+1] = p;
				++pos;
			}
			points.pop();
		}*/
		
	}
	
	
}